﻿#pragma once
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <iostream>
#include <QMainWindow>
#include <QSignalMapper>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QPainter>
#include <QKeyEvent>
#include <QQueue>
#include <QTimer>
#include <QStackedWidget>
#include <QSpacerItem>
#include <QMessageBox>
#include <QStringList>
#include <string>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <QProgressBar>
#include <QProcess>
#include <stack>
#include <fstream>
#include <stdlib.h>
#include "block.h"
#include "simpletest.h"

using namespace std;

//QT_BEGIN_NAMESPACE
//namespace Ui { class MainWindow; }
//QT_END_NAMESPACE

//有方块场地长和宽、方块种类数
const int X = 8;
const int Y = 12;
const int picNum = 12;


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    friend class SimpleTest;

public slots:
    //单人模式开始
    void singleModeStart();
    //多人模式开始
    void multiModeStart();
    //与时间关联的函数
    void showCurTime();
    //游戏暂停
    void gamePause();
    //保存游戏
    void saveGame();
    //载入游戏
    void loadGame();
    //退出游戏
    void quit();
    //返回主菜单
    void returnDlg();
    //闪现槽函数
    void playerFlash(int);
    //重新开始
    void restart();

public:signals:
    void quitGame();
    void returnLogindlg();
    //游戏结束信号
    void gameOver();
    //载入文件失败信号
    void loadFileFail();

protected:
    virtual void keyPressEvent(QKeyEvent *event) override;

private:
    struct Pos{
        int x,y;
    public:
        Pos(){}
        Pos(int x,int y){
            this->x = x;
            this->y = y;
        }
        void operator = (const Pos &m)
        {
            x = m.x;
            y = m.y;
        }
        bool operator == (const Pos &m)
        {
            return x == m.x && y == m.y;
        }

    };
    //模式 0单人 1多人
    int mode;
    //地图数组 周围两圈是空地
    int map[X+4][Y+4];
    //辅助地图打乱的数组
    int randomMap[X*Y];
    //剩余时间
    int remainingTime;
    //当前窗口
    int curScreen;
    //分数
    int score[2];
    int blockNum = X*Y;
    //闪现起始时间
    int flashStart;
    //闪现权限
    bool flashPermission = false;
    //记录道具是否出现过
    bool if1s;
    bool ifFlash;
    bool ifShuffle;
    //方块消除辅助数组
    Pos firstPos[3],secondPos[3];
    //玩家位置
    Pos player1Pos,player2Pos;
    //道具位置
    Pos propPos[3];
    //用于显示的地图数组
    Block *blocks[X+4][Y+4];
    //玩家 道具 路径对应图片
    QPixmap player1,player2;
    QPixmap propPic[3];
    QPixmap pathPic[18];
    //检查是否有解的辅助数组
    QQueue<Pos> checkFrozen;
    //保存图像文件的路径
    QStringList block1,block2,propList;
    //信号批量处理
    QSignalMapper *mapper[X+4][Y+4];
    //界面布局
    QGridLayout *gridLayout;
    QWidget *widget;
    QWidget *pauseWindow;
    QWidget *toolWidget;
    QStackedWidget *mainWindow;
    QVBoxLayout *vBoxLayout;
    QVBoxLayout *pauseLayout;
    QHBoxLayout *hBoxLayout;
    //进度条
    QProgressBar *progressBar;
    QPushButton *pause;
    QPushButton *pauseButton[5];
    QLabel *timeReminder;
    QLabel *scoreShow;
    QLabel *curResult;
    QLabel *pauseShow;
    QTimer *timer;
    enum{
        prop1s = 1,propFlash,propShuffle
    };
    //初始化相关变量
    void initArray();
    void loadImg();
    void arrangeImg(const QStringList &block1, const QStringList &block2);
    Block *createBlock(const QString &str1,const QString &str2);
    //界面布局设置
    void setWindow();
    void setToolWidget();
    void setPauseWindow();
    //初始化玩家位置及图像
    void initPlayerPos();
    //根据玩家位置刷新玩家图像
    void flushPlayerPos();
    //地图重排
    void shuffleBlocks();
    //激活方块
    void activeBlock(int x, int y,bool plr);
    void handleProp(int num);
    //随机放置道具
    void placeProp(int num);
    //游戏结束时的处理函数
    void ifGameOver();
    //判断选中的两个方块能否消除 是否画线
    bool checkRemovable(int num, bool draw);
    //判断剩余方块是否有解
    bool ifFrozen();
    //判断方块是否可接触
    bool ifAtEdge(int x,int y);
    //是否可通过直线连接
    bool canLinkDirectly(int x1,int y1,int x2,int y2, bool draw);
    //是否可通过两段折线连接
    bool canLinkWithOneCorner(int x1,int y1,int x2,int y2, bool draw);
    //是否可通过三段折线连接
    bool canLinkWithTwoCorner(int x1,int y1,int x2,int y2, bool draw);
    //在空地上选取随机位置
    Pos randomPos();
    //在最外圈空地选取随机位置用于放置道具
    Pos randomPropPos();


};
#endif // MAINWINDOW_H
